<?php

class Seo
{
	//--------------------------------------------------------------------------
	//
	//  Instance properties
	//
	//--------------------------------------------------------------------------
	public $currentState;
	private $defaultStateId, $states, $vars, $lang;
	
	//--------------------------------------------------------------------------
	//
	//  API
	//
	//--------------------------------------------------------------------------
	/**
	 * Initialize the SEO manager.
	 */
	public function init($swfaddress, $lang = "fr", $configURL = "web/xml/config/site.xml")
	{
		$configXML = simplexml_load_string(file_get_contents($configURL));
		$seofileKey = "seofile";
		$this->lang = $lang;
		
		// Parse config vars.
		$this->vars = array();
		foreach ($configXML->vars->var as $var) {
			$name = (string) $var["name"];
			$key = ($name == $seofileKey || $name == "state") ? $name : '{'.$name.'}';
			$this->vars[$key] = (string) $var;
		}
		
		// Get default state.
		$this->defaultStateId = $this->vars["state"];
		
		// Parse config states.
		$this->states = array();
		foreach ($configXML->states->state as $state) {
			$id = (string) $state["id"];
			$this->states[$id]["swfaddress"] = (string) $state["swfaddress"];
		}
		
		// Get SEO file URL.
		$seoURL = $this->resolvePath($this->vars[$seofileKey]);
		$seoXML = simplexml_load_string(file_get_contents($seoURL));
		$seofileKey = "seofile";
		
		// Parse SEO states.
		foreach ($seoXML->state as $state) {
			if ($id == $this->defaultStateId) {
				$this->states[$id] = array_merge($this->states[$id], $this->parseState($state));
			}
		}
		foreach ($seoXML->state as $state) {
			$id = (string) $state["id"];
			if (!empty($this->states[$id])) {
				$this->states[$id] = array_merge($this->states[$id], $this->parseState($state));
			}
		}
		
		$this->currentState = $this->getCurrentState($swfaddress);
	}
	
	/**
	 * Get the meta related to specific name.
	 */
	public function getMeta($name)
	{
		return $this->currentState[$name];
	}
	
	/**
	 * Write Open Graph related metas.
	 */
	public function writeOGMetas()
	{
		if (!$this->currentState) {
			die("Call Seo::init() method before attempt to get meta !");
		}
		foreach ($this->currentState["og"] as $key=>$value) {
			$value = empty($value) ? $this->states[$this->defaultStateId]["og"][$key] : $value;
			if (!empty($value)) {
				echo '<meta property="og:'.$key.'" content="'.$value.'" />';
			}
		}
	}
	
	/**
	 * Write metas navigation.
	 */
	public function writeMetaNav($base)
	{
		echo '<ul class="nav">';
		foreach ($this->states as $key=>$value) {
			echo '<li><a href="'.$base.$value["swfaddress"].'">'.$value["title"].'</a></li>';
		}
		echo '</ul>';
	}
	
	
	//--------------------------------------------------------------------------
	//
	//  Methods
	//
	//--------------------------------------------------------------------------
	/**
	 * Resolve path binding. 
	 */
	private function resolvePath($path)
	{
		global $p;
		$p = strtr($path, $this->vars);
		if (strpos($p, "{") !== false) {
			if (strrpos($p, "{l}") !== false) {
				$p = implode($this->lang, explode("{l}", $p));
			}
			$this->resolvePath($p);
		}
		return $p;
	}
	
	/**
	 * Parse SEO for each state.
	 * If metas are missing, defaultState metas are used by default. 
	 */
	private function parseState($state)
	{
		$meta = array();
		$keys = array("title", "description", "keywords", "altContent");
		foreach ($keys as $key) {
			$value = (string) $state->$key;
			$meta[$key] = empty($value) ? $this->states[$this->defaultStateId][$key] : $value;
		}
		
		// Open graph meta.
		if (count($state->facebook->children()) === 0) {
			$meta["og"] = $this->states[$this->defaultStateId]["og"];
		} else {
			foreach ($state->facebook->children() as $node=>$child) {
				$value = (string) $child;
				if (strripos($value, "{") !== false) {
					$value = $this->resolvePath($value);
				}
				$meta["og"][$node] = empty($value) ? $this->states[$this->defaultStateId]["og"][$node] : $value;
			}
		}
		
		return $meta;
	}
	
	/**
	 * Set current swfaddress and get current state.
	 */
	private function getCurrentState($swfaddress)
	{
		$swfaddress = "/".implode("/", $swfaddress);
		foreach ($this->states as $state) {
			if ($swfaddress == $state["swfaddress"]) {
				return $state;
			}
		}
		return $this->states[$this->defaultStateId];
	}
}

?>